From: Keir Fraser Date: Wed, 22 Oct 2008 10:59:19 +0000 (+0100) Subject: EPT: tidy exception handler to give more useful errors X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14054^2~56 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22man:///%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22man:/?a=commitdiff_plain;h=c916f30553fc9df0959932324b056d316e603b3f;p=xen.git EPT: tidy exception handler to give more useful errors Signed-off-by: Tim Deegan --- diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index ed99ec8073..7e36167019 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1964,27 +1964,25 @@ static void ept_handle_violation(unsigned long qualification, paddr_t gpa) { unsigned long gla_validity = qualification & EPT_GLA_VALIDITY_MASK; struct domain *d = current->domain; - unsigned long gfn = gpa >> PAGE_SHIFT; + unsigned long gla, gfn = gpa >> PAGE_SHIFT; mfn_t mfn; p2m_type_t t; - if ( unlikely(qualification & EPT_GAW_VIOLATION) ) - { - gdprintk(XENLOG_ERR, "EPT violation: guest physical address %"PRIpaddr - " exceeded its width limit.\n", gpa); - goto crash; - } + mfn = gfn_to_mfn(d, gfn, &t); - if ( unlikely(gla_validity == EPT_GLA_VALIDITY_RSVD) || - unlikely(gla_validity == EPT_GLA_VALIDITY_PDPTR_LOAD) ) + /* There are two legitimate reasons for taking an EPT violation. + * One is a guest access to MMIO space. */ + if ( gla_validity == EPT_GLA_VALIDITY_MATCH && p2m_is_mmio(t) ) { - gdprintk(XENLOG_ERR, "EPT violation: reserved bit or " - "pdptr load violation.\n"); - goto crash; + handle_mmio(); + return; } - mfn = gfn_to_mfn(d, gfn, &t); - if ( (t != p2m_ram_ro) && p2m_is_ram(t) && paging_mode_log_dirty(d) ) + /* The other is log-dirty mode, writing to a read-only page */ + if ( paging_mode_log_dirty(d) + && (gla_validity == EPT_GLA_VALIDITY_MATCH + || gla_validity == EPT_GLA_VALIDITY_GPT_WALK) + && p2m_is_ram(t) && (t != p2m_ram_ro) ) { paging_mark_dirty(d, mfn_x(mfn)); p2m_change_type(d, gfn, p2m_ram_logdirty, p2m_ram_rw); @@ -1992,16 +1990,39 @@ static void ept_handle_violation(unsigned long qualification, paddr_t gpa) return; } - /* This can only happen in log-dirty mode, writing back A/D bits. */ - if ( unlikely(gla_validity == EPT_GLA_VALIDITY_GPT_WALK) ) - goto crash; - - ASSERT(gla_validity == EPT_GLA_VALIDITY_MATCH); - handle_mmio(); - - return; + /* Everything else is an error. */ + gla = __vmread(GUEST_LINEAR_ADDRESS); + gdprintk(XENLOG_ERR, "EPT violation %#lx (%c%c%c/%c%c%c), " + "gpa %#"PRIpaddr", mfn %#lx, type %i.\n", + qualification, + (qualification & EPT_READ_VIOLATION) ? 'r' : '-', + (qualification & EPT_WRITE_VIOLATION) ? 'w' : '-', + (qualification & EPT_EXEC_VIOLATION) ? 'x' : '-', + (qualification & EPT_EFFECTIVE_READ) ? 'r' : '-', + (qualification & EPT_EFFECTIVE_WRITE) ? 'w' : '-', + (qualification & EPT_EFFECTIVE_EXEC) ? 'x' : '-', + gpa, mfn_x(mfn), t); + + if ( qualification & EPT_GAW_VIOLATION ) + gdprintk(XENLOG_ERR, " --- GPA too wide (max %u bits)\n", + 9 * (unsigned) d->arch.hvm_domain.vmx.ept_control.gaw + 21); + + switch ( gla_validity ) + { + case EPT_GLA_VALIDITY_PDPTR_LOAD: + gdprintk(XENLOG_ERR, " --- PDPTR load failed\n"); + break; + case EPT_GLA_VALIDITY_GPT_WALK: + gdprintk(XENLOG_ERR, " --- guest PT walk to %#lx failed\n", gla); + break; + case EPT_GLA_VALIDITY_RSVD: + gdprintk(XENLOG_ERR, " --- GLA_validity 2 (reserved)\n"); + break; + case EPT_GLA_VALIDITY_MATCH: + gdprintk(XENLOG_ERR, " --- guest access to %#lx failed\n", gla); + break; + } - crash: domain_crash(d); }